package main

import (
	"encoding/binary"
	"encoding/json"
	"fmt"
	"log"

	"github.com/boltdb/bolt"
)

func main() {
	// Open the my.db data file in your current directory.
	// It will be created if it doesn't exist.
	db, err := bolt.Open("bolt.db", 0600, nil)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	bname := "user"
	db.Update(func(tx *bolt.Tx) error {
		_, err := tx.CreateBucketIfNotExists([]byte(bname))
		if err != nil {
			return fmt.Errorf("create bucket '%s' failed: %s", bname, err)
		}
		return nil
	})

	err = CreateUser(db, &User{})
	if err != nil {
		fmt.Printf("create user failed: %s\n", err)
		return
	}

	db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("user"))
		c := b.Cursor()
		for k, v := c.First(); k != nil; k, v = c.Next() {
			fmt.Printf("key=%d, value=%s\n", btoi(k), string(v))
		}
		return nil
	})
}

func CreateUser(db *bolt.DB, u *User) error {
	return db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("user"))

		id, _ := b.NextSequence()
		u.ID = int(id)

		buffer, err := json.Marshal(u)
		if err != nil {
			return err
		}

		return b.Put(itob(u.ID), buffer)
	})
}

func itob(v int) []byte {
	b := make([]byte, 8)
	binary.BigEndian.PutUint64(b, uint64(v))
	return b
}

func btoi(b []byte) int {
	return int(binary.BigEndian.Uint64(b))
}

type User struct {
	ID int
}
